<template>
  <Form class="space-y-4" @submit="onSubmit">
    <div
      v-for="{
        as,
        name,
        label,
        rules,
        type,
        placeholder,
        ...attrs
      } in formSchema.fields"
      :key="name"
      class="form-field"
    >
      <label :for="name" class="mb-1 block text-sm font-medium text-gray-700">{{
        label
      }}</label>
      <Field
        :id="name"
        :as="as"
        :name="name"
        :placeholder="placeholder"
        :rules="rules"
        :type="type"
        :validate-on-blur="false"
        :validate-on-input="true"
        class="w-full rounded-md border border-gray-300 px-3 py-2 focus:border-transparent focus:outline-none focus:ring-2 focus:ring-blue-500"
        v-bind="attrs"
      />
      <ErrorMessage
        :name="toValue(name)"
        as="p"
        class="animate__animated animate__bounce mt-1 text-sm text-red-500"
      />
    </div>
    <button
      class="w-full rounded-md bg-blue-500 px-4 py-2 text-white hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2"
      type="submit"
    >
      提交表单
    </button>
  </Form>
</template>
<script setup lang="ts">
import { toValue } from 'vue';

import { toTypedSchema } from '@vee-validate/zod';
import { ErrorMessage, Field, Form } from 'vee-validate';
import { z } from 'zod';

import 'animate.css';

const onSubmit = () => {
  // 表单验证通过后的处理逻辑
};

// 定义表单验证模式
const formSchema = {
  fields: [
    {
      label: '姓名',
      name: 'name',
      as: 'input',
      placeholder: '请输入您的姓名',
      rules: toTypedSchema(
        z
          .string({
            message: '姓名至少需要2个字符',
          })
          .min(2, { message: '姓名至少需要2个字符' }),
      ),
    },
    {
      label: '邮箱',
      name: 'email',
      as: 'input',
      type: 'email',
      placeholder: '请输入您的邮箱',
      rules: 'email',
    },
    {
      label: '密码',
      name: 'password',
      as: 'input',
      type: 'password',
      placeholder: '请输入密码',
      rules: toTypedSchema(
        z
          .string({
            message: '密码至少需要6个字符',
          })
          .min(6, { message: '密码至少需要6个字符' }),
      ),
    },
    {
      label: '确认密码',
      name: 'confirmPassword',
      as: 'input',
      type: 'password',
      placeholder: '请再次输入密码',
      rules: toTypedSchema(z.string().min(1, { message: '请确认密码' })),
    },
    {
      label: '年龄',
      name: 'age',
      as: 'select',
      type: 'number',
      placeholder: '请输入年龄',
    },
  ],
};
</script>

<style scoped>
.form-field {
  margin-bottom: 1rem;
}
</style>
